#ifndef UDOCK_H
#define UDOCK_H

#include <unordered_set>
#include <vector>
#include "window.h"
#include "structs.h"

namespace UDock {

class ILayoutManager;
class DockManager;

typedef struct  {

} PolicyProvider;

enum DockOption {
    NoDock = 0,
    Left = 1,
    Right = 2,
    Top = 4,
    Bottom = 8,
    Tabbed = 16,
    CROSS = 15
};


class IWidget {
public:
    virtual void move(const Point & point) = 0;
    virtual bool undocked() = 0;
    virtual Window window() = 0;
};

class IDockItem : public IWidget {

};

class IDockWidget : public IDockItem{

};

class IBaseDock : public IDockItem{
public:
//    virtual void showBaseIndicators(DockOption dockoption) = 0;
//    virtual void hideBaseIndicators() = 0;


};

class IDockLayout {

};

class IDockWidgetPreviewer{
public:
    virtual void previewBasicDocks(IDockItem* dragged_item) = 0;
    virtual std::unordered_set<Window> previewWidgets() = 0;
    virtual void showDockIndicators(IDockItem* target, DockOption dockoptions) = 0;
    virtual void showDockPreview(IDockItem* dragged_item, IDockItem* target, DockOption dockoption) = 0;
    virtual void moveWidget(IDockItem* widget, const Point & point, const Point & offset) = 0;
    virtual void hidePreviews() = 0;
    virtual void setDockManager(DockManager* dockmanager) = 0;
    virtual DockOption hoveredIndicator(const Point & point, IDockItem* target) = 0;
    virtual void unHover() = 0;


};




class IPolicyManager{
public:
    virtual bool isRepositionable(IWidget* widget) = 0;
    virtual bool isDetachable(IWidget* widget) = 0;
    virtual DockOption dockOptions(IWidget* dragged_widget, IWidget* target) = 0;
    virtual void setDockManager(DockManager* dockmanager) = 0;
};

class DockManager {
    enum State {
        DEFAULT = 0,
        DRAGGING = 1
    };

public:
    DockManager();
    void mouseDown(IDockItem *widget, const Point &point, const Point &offset);
    void mouseMove(IDockItem* widget, const Point &point);
    void mouseUp(IDockItem* widget, const Point & point);
public:
    IDockWidgetPreviewer* previewer(){return m_previewer;}
    void setPreviewer(IDockWidgetPreviewer* previewer){m_previewer = previewer;
                                                       previewer->setDockManager(this);}

    IPolicyManager* policyManager(){return m_policymanager;}
    void setPolicyManager(IPolicyManager* policymanager){m_policymanager= policymanager;
                                                       policymanager->setDockManager(this);}

    ILayoutManager* layoutManager(){return m_layoutmanager;}
    void setLayoutManager(ILayoutManager* ilym){m_layoutmanager = ilym;}
protected:
    void startDrag(const Point &point);
protected:
    IDockWidgetPreviewer* m_previewer;
    ILayoutManager* m_layoutmanager;
    IPolicyManager* m_policymanager;
    std::vector<Window> m_windows;
    std::vector<IDockItem*> m_dockitems;
    State m_state;
    IDockItem* dragging;
    Point offset, dragstart;
    int m_dragtolerance;

};

class ILayoutManager {
public:
    virtual IBaseDock* baseDockFromPoint(Window target_window, const Point& point) =0;
    virtual IDockItem* itemFromPoint(IBaseDock* target_window, const Point& point) =0;
    virtual Rect dockedSize(IDockItem* dragged_widget, IWidget* target_widget, DockOption dockoption) =0;
    virtual void dock(IDockItem* dragged_widget, IWidget* target_widget, DockOption dockoption) = 0;
    virtual std::unordered_set<IBaseDock*> getBasicDocks() = 0;
    virtual void addBaseDock(IBaseDock* base_dock) = 0;
};

}

#endif // UDOCK_H
